package znet

import (
	"fmt"
	"net"

	"github.com/desyang-hub/zinx_demo/utils"
	"github.com/desyang-hub/zinx_demo/zface"
)

type Server struct {
	Name       string
	IPVersion  string
	Ip         string
	Port       int
	MsgHandler zface.IMsgHandler
}

// func CallBackToClient(conn *net.TCPConn, buf []byte, n int) error {
// 	// 直接写回
// 	if _, err := conn.Write(buf[:n]); err != nil {
// 		return errors.New("func CallBackToClient err: " + err.Error())
// 	}
// 	return nil
// }

// Start implements zface.IServer.
func (server *Server) Start() {
	// 获取一个服务地址
	tcpAddr, err := net.ResolveTCPAddr(server.IPVersion, fmt.Sprintf("%s:%d", server.Ip, server.Port))

	if err != nil {
		fmt.Println("resovle tcp addr err: ", err)
		return
	}

	fmt.Println("Server name: ", server.Name)

	// 监听该服务器地址
	tcpListener, err := net.ListenTCP(server.IPVersion, tcpAddr)
	if err != nil {
		fmt.Println("listen tcp err: ", err)
		return
	}

	fmt.Printf("[start] server listener at http://%s:%d\n", server.Ip, server.Port)

	// 启用MsgHandler工作线程池
	server.MsgHandler.StartWorkerPool()

	// 阻塞监听用户请求
	for {
		conn, err := tcpListener.AcceptTCP()

		if err != nil {
			fmt.Println("tcp accept err: ", err)
			continue
		}

		fmt.Println("Receive Connection Requist from ", conn.RemoteAddr().String())

		// 建立Connection
		var cid uint32 = 0
		c := NewConnection(conn, cid, server.MsgHandler)

		// 启动链接监听
		c.Start()
	}
}

// Serve implements zface.IServer.
func (server *Server) Serve() {
	go server.Start()

	// 阻塞进程做一些别的服务
	select {}
}

// Stop implements zface.IServer.
func (server *Server) Stop() {
	// TODO: 回收一些服务器资源
	panic("unimplemented")
}

func (server *Server) AddRouter(msgID uint32, router zface.IRouter) {
	server.MsgHandler.AddRouter(msgID, router)
}

// 构造方法
func NewServer() (server zface.IServer) {
	server = &Server{
		Name:       utils.AppContext.Name,
		IPVersion:  "tcp4",
		Ip:         utils.AppContext.Ip,
		Port:       utils.AppContext.Port,
		MsgHandler: NewMsgHandler(),
	}

	utils.AppContext.TcpServer = server

	return server
}
